---
title: Publishing Packages
description: A guide on how to publish packages to Zoi registries and create your own.
---

This guide covers how to publish your package to the official Zoi repositories, and how to create and manage your own private or public package repositories.

## Publishing to Official Repositories

Once your `.pkg.lua` file works locally, it's time to share it with the world! This is done by adding your package file to the official Zoi packages database.

The Zoi package database is hosted on GitLab and mirrored on GitHub and Codeberg.

- **GitLab (Primary):** [Zillowe/Zillwen/Zusty/Zoidberg](https://gitlab.com/Zillowe/Zillwen/Zusty/Zoidberg)
- **GitHub (Mirror):** [Zillowe/Zoidberg](https://github.com/Zillowe/Zoidberg)
- **Codeberg (Mirror):** [Zillowe/Zoidberg](https://codeberg.org/Zillowe/Zoidberg)

You can contribute by opening a **Merge Request** to the GitLab repository, or by **opening an issue** to request a new package. The following steps outline the process for creating a Merge Request on GitLab, which is very similar to the process on GitHub.

1.  **Fork the Repository:**
    Go to the repository's page on GitLab or GitHub and click the "Fork" button to create your own copy.

2.  **Clone Your Fork:**
    Clone the repository to your local machine.

    ```sh
    # For GitLab
    git clone https://gitlab.com/YourUsername/Zoidberg.git
    cd Zoidberg
    ```

3.  **Choose the Right Directory:**
    As discussed in the [creating packages guide](/docs/zds/zoi/creating-packages), you should almost always add new packages to the `community` directory.

    You can also create nested directories to better organize packages. For example, you could place a Linux-specific editor in `community/editors/linux/my-editor/my-editor.pkg.lua`. The `repo` field in your package file should then be `community/editors/linux`.

4.  **Add Your Package File:**
    Copy your `my-package.pkg.lua` file into the `community/my-package/` directory.

    ```sh
    cp /path/to/my-package.pkg.lua community/my-package/
    ```

    For a nested repository, create the directory structure and place your file inside:

    ```sh
    mkdir -p community/editors/linux/my-editor
    cp /path/to/my-editor.pkg.lua community/editors/linux/my-editor/
    ```

5.  **Commit and Push:**
    Commit your new package file to your forked repository.

    ```sh
    git add community/my-package/my-package.pkg.lua
    git commit -m "feat(community): add my-package v1.2.3"
    git push origin main
    ```

    For a nested package, your commit might look like this:

    ```sh
    git add community/editors/linux/my-editor/my-editor.pkg.lua
    git commit -m "feat(community): add my-editor v1.0.0"
    git push origin main
    ```

6.  **Open a Merge/Pull Request:**
    Go to your forked repository on GitLab or GitHub. You should see a button to "Create merge request" or "Create pull request". Click it.
    - **Title:** Use a conventional commit message like `feat(community): add my-package`.
    - **Description:** Briefly describe what your package does and link to its official website or source code.
    - Submit the request.

A Zoi maintainer will review your submission. They may suggest some changes. Once approved, it will be merged, and your package will be available to everyone after the next `zoi sync`!

Once your package is merged, it will also be visible on the [Nel Registry](https://nel.zillowe.qzz.io).

## Advanced: Publishing Pre-Built Packages

While the above method works for publishing package definitions (`.pkg.lua`), the official Zoi repositories store pre-built package archives (`.pkg.tar.zst`) for faster and more reliable installations. This avoids having every user download assets from upstream URLs.

You can create these archives yourself using the `zoi package` command set. This is the same workflow used by Zoi's CI/CD.

1.  **Generate Metadata:**
    Run `zoi package meta` on your `.pkg.lua` file. This creates a `.meta.json` file, resolving all dynamic Lua code into a static list of assets for all platforms. You can use the `--type` flag to target a specific installation method (e.g. `zoi package meta ./my-package.pkg.lua --type source`).

    ```sh
    zoi package meta ./my-package.pkg.lua
    ```

2.  **Build the Archive:**
    Run `zoi package build` on the generated metadata file. This command downloads the assets for your **current platform** (or builds them from source, potentially inside a Docker container if specified), verifies them, and creates a distributable `.pkg.tar.zst` archive.

    ```sh
    zoi package build ./my-package.meta.json
    ```

3.  **Publish the Archive:**
    You can then upload this `.pkg.tar.zst` archive to a web server or a release page. The official Zoi repositories are hosted on a dedicated server. For community contributions, you would typically provide the `.pkg.lua` file in your pull request, and the Zoi maintainers would handle the build and hosting of the archive.

## Creating Your Own Git-Based Package Repository

While contributing to the official repositories is great for public packages, you might want to manage your own set of packages for private projects, company-internal tools, or personal use. Zoi makes this easy by allowing you to add any git repository as a package source.

### Step 1: Create Your Git Repository

1.  Create a new, empty repository on a service like GitLab or GitHub.
2.  Add your `*.pkg.lua` files to the root of the repository. The structure is simple: just a flat collection of package files. You can also create nested directories.

    ```
    my-zoi-repo/
    ├── my-first-package.pkg.lua
    └── my-second-package.pkg.lua
    ```

3.  Commit and push your files to the remote repository.

### Step 2: Add Your Repository to Zoi

Use the `zoi repo add` command with your repository's HTTPS or SSH URL. Zoi will clone it locally.

```sh
zoi repo add https://github.com/YourUsername/my-zoi-repo.git
```

Zoi clones the repo into `~/.zoi/pkgs/git/`. The name of the repository is determined from the URL (e.g. `my-zoi-repo`).

### Step 3: Install Packages from Your Repository

To install a package from your custom git repository, use the `@git/` prefix, followed by the repository name and the package name.

```sh
# To install my-first-package from the example above
zoi install @git/my-zoi-repo/my-first-package
```

This allows you to maintain and version your own collections of packages completely independently from the official Zoi databases.

## Creating Your Own Zoi-Type Package Registry

For advanced use cases, such as creating a corporate mirror or a completely separate package ecosystem, you can create your own Zoi-type package registry. This is a git repository that mimics the structure of the official Zoidberg database.

### Step 1: Set Up the Registry Repository

1.  Create a new git repository.
2.  Create a `repo.yaml` file in the root of your repository to define its properties. See the [Repositories guide](/docs/zds/zoi/repositories#the-repoyaml-file) for details on the available fields. A minimal example would be:
    ```yaml
    name: My Custom Registry
    description: A collection of my personal packages.
    repo-git: https://github.com/YourOrg/my-zoi-registry.git
    ```
3.  Structure the rest of your repository like the official Zoidberg database, with directories for tiers like `core`, `main`, `community`, etc.

    ```
    my-zoi-registry/
    ├── repo.yaml
    ├── core/
    │   └── ...
    ├── main/
    │   └── ...
    └── community/
        └── my-package/my-package.pkg.lua
    ```

### Step 2: Point Zoi to Your Registry

Users can configure their Zoi client to use your new registry instead of the default one.

#### Using `zoi sync set`

The easiest way for a user to switch to your registry is with the `zoi sync set` command:

```sh
zoi sync set https://github.com/YourOrg/my-zoi-registry.git
```

This command updates the registry URL in Zoi's configuration. The next time `zoi sync` is run, it will pull from your repository.

#### Using an Extension

For a more user-friendly approach, you can distribute an `extension` package that configures the registry automatically.

Create a `.pkg.lua` file for your extension:

```lua
-- my-registry-ext.pkg.lua
package({
  name = "my-registry-ext",
  repo = "community",
  type = "extension",
  version = "1.0",
  description = "Configures Zoi to use MyOrg's internal package registry.",
  extension = {
    type = "zoi",
    changes = {
      { type = "registry-repo", add = "https://github.com/YourOrg/my-zoi-registry.git" }
    }
  }
})
```

Publish this extension (e.g. in a separate git repository that users can add). Users can then run `zoi extension add my-registry-ext` to switch to your registry. This is a clean way to manage the configuration change. For more details, see the [Extensions guide](/docs/zds/zoi/extensions).

## Making a Git Repository Directly Installable

You can make a Git repository directly installable via `zoi install --repo <repo-spec>` by placing a `zoi.yaml` file in its root. This file tells Zoi what package to install from your repository.

**Example `zoi.yaml`:**

```yaml
# zoi.yaml in the root of your repository
package: "my-awesome-package"
```

The `package` field can be:

- A package name (e.g. `my-package` or `@my-repo/my-package`). Zoi will resolve this from the official repositories.
- A relative path to a `.pkg.lua` file in the repository.
- A full URL to a raw `.pkg.lua` file.

With this file in place, users can install the package from your repository without adding it first:

```sh
# Install from GitHub (default)
zoi install --repo YourUsername/my-zoi-repo

# Install from GitLab
zoi install --repo gl:YourUsername/my-zoi-repo
```
